package com.zmn.plat.business.impl.contract;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.*;
import java.util.*;
import java.util.stream.Collectors;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.alibaba.dubbo.config.annotation.Reference;
import com.google.common.collect.Maps;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.math.MathUtil;
import com.zmn.common.utils.office.excel.ExportExcel;
import com.zmn.common.utils.pager.LayuiPageUtil;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.mcc.cas.model.LoginStaff;
import com.zmn.mcc.common.dto.staff.StaffDRO;
import com.zmn.mcc.dubbo.interfaces.staff.StaffListRemoteService;
import com.zmn.plat.business.interfaces.contract.ContractRecordBService;
import com.zmn.plat.common.dictionary.*;
import com.zmn.plat.common.exception.PlatException;
import com.zmn.plat.dubbo.utils.DubboConsts;
import com.zmn.plat.manager.dictionary.MasterDict;
import com.zmn.plat.model.entity.contract.file.record.ContractFileRecord;
import com.zmn.plat.model.entity.contract.record.ContractRecord;
import com.zmn.plat.model.entity.contract.record.ContractRecordQuery;
import com.zmn.plat.model.vo.contract.record.ContractRecordExportExcelVO;
import com.zmn.plat.model.vo.contract.record.ContractRecordVO;
import com.zmn.plat.services.interfaces.contract.file.record.ContractFileRecordService;
import com.zmn.plat.services.interfaces.contract.record.ContractRecordService;

/**
 * 类描述：订单配置-跟单内容DocumentaryContentBServiceImpl
 *
 * @author linfeng
 * @since 2019/10/22/13:54
 */
@Service
public class ContractRecordBServiceImpl implements ContractRecordBService {
    private Logger logger = LoggerFactory.getLogger(ContractRecordBServiceImpl.class);

    @Resource
    ContractRecordService contractRecordService;

    @Resource
    ContractFileRecordService contractFileRecordService;

    @Reference(version = DubboConsts.INTERFACE_VERSION, check = false)
    StaffListRemoteService staffService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer insert(ContractRecordVO contractRecordVO, String opertor) {
        Date now = DateUtil.getNow();

        ContractRecordQuery query = new ContractRecordQuery();
        query.setName(contractRecordVO.getName());
        List<ContractRecord> contractRecords = contractRecordService.listByQuery(query);

        if (contractRecords != null && contractRecords.size() > 0) {
            throw new PlatException("已经存在同名称的合同数据！");
        }

        ContractRecord contractRecord = new ContractRecord();
        BeanUtils.copyProperties(contractRecordVO, contractRecord);
        if (contractRecord.getSort() == null) {
            Integer sort = contractRecordService.findMaxSort();
            sort = sort == null ? 1 : sort + 1;
            contractRecord.setSort(sort);
        }

        StaffDRO staff = staffService.getStaff(contractRecord.getAgent()).getData();
        if (staff != null) {
            contractRecord.setAgentStr(staff.getRealName() + "_" + staff.getMobile());
        }

        String contractNo = getContractNo(contractRecord.getAgentCompanyId(), contractRecord.getAgentDeptOneId());
        contractRecord.setContractNo(contractNo);
        contractRecord.setCreater(opertor);
        contractRecord.setCreateTime(now);
        contractRecord.setUpdater(opertor);
        contractRecord.setUpdateTime(now);
        contractRecord.setFirstAlertStatus(GlobalConsts.NO);
        contractRecord.setSecondAlertStatus(GlobalConsts.NO);
        contractRecord.setOverdueAlertStatus(GlobalConsts.NO);
        contractRecordService.insert(contractRecord);

        List<ContractFileRecord> fileRecords = contractRecordVO.getContractFileRecords();
        fileRecords.forEach(e -> {
            e.setContractId(contractRecord.getContractId());
            e.setCreater(opertor);
            e.setCreateTime(now);
            e.setUpdater(opertor);
            e.setUpdateTime(now);
        });

        if (!CollectionUtils.isEmpty(fileRecords)) {
            contractFileRecordService.insertBatch(fileRecords);
        }

        return contractRecordVO.getContractId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(ContractRecordVO contractRecordVO, String opertor) {
        Date now = DateUtil.getNow();

        ContractRecordQuery query = new ContractRecordQuery();
        query.setName(contractRecordVO.getName());
        List<ContractRecord> contractRecords = contractRecordService.listByQuery(query);

        if (contractRecords != null && contractRecords.size() > 0) {
            if (contractRecords.size() > 1 || !Objects.equals(contractRecords.get(0).getContractId(), contractRecordVO.getContractId())) {
                throw new PlatException("已经存在同名称的合同数据！");
            }
        }

        ContractRecord contractRecord = new ContractRecord();
        BeanUtils.copyProperties(contractRecordVO, contractRecord);
        contractRecord.setUpdater(opertor);
        contractRecord.setUpdateTime(now);

        StaffDRO staff = staffService.getStaff(contractRecord.getAgent()).getData();
        if (staff != null) {
            contractRecord.setAgentStr(staff.getRealName() + "_" + staff.getMobile());
        }

        contractRecordService.updateByKey(contractRecord);

        contractFileRecordService.deleteByContractId(contractRecordVO.getContractId());
        List<ContractFileRecord> fileRecords = contractRecordVO.getContractFileRecords();
        fileRecords.forEach(e -> {
            e.setCreater(opertor);
            e.setCreateTime(now);
            e.setUpdater(opertor);
            e.setUpdateTime(now);
        });

        if (!CollectionUtils.isEmpty(fileRecords)) {
            contractFileRecordService.insertBatch(fileRecords);
        }
    }

    @Override
    public ExportExcel<ContractRecordExportExcelVO> exportExcel(ContractRecordQuery query, LoginStaff staff) {
        // 格式化时间选择器时间
        if (!StringUtil.isBlank(query.getSignBeginAndEndDay())) {
            String[] strings = LayuiPageUtil.dateIntercept(query.getSignBeginAndEndDay());
            query.setSignBeginDay(DateUtil.getDateStart(DateUtil.parse(strings[0], DateUtil.FORMAT_DATE)));
            query.setSignEndDay(DateUtil.getDateEnd(strings[1], DateUtil.FORMAT_DATE));
        }

        List<ContractRecordVO> items = contractRecordService.listPageByQuery(query);
        items.forEach(e -> {
            e.setSubjectAmountYuan(narrow(e.getSubjectAmount()));
        });
        List<ContractRecordExportExcelVO> contractRecordExportExcelVOS = new ArrayList<>();

        List<ContractFileRecord> contractFileRecords = contractFileRecordService.listAll();
        Map<Integer, List<ContractFileRecord>> fileRecordMap = contractFileRecords.stream().collect(Collectors.groupingBy(ContractFileRecord::getContractId));

        for (int i = 0; i < items.size(); i++) {
            ContractRecordVO e = items.get(i);
            ContractRecordExportExcelVO contractRecordExportExcelVO = new ContractRecordExportExcelVO();
            BeanUtils.copyProperties(e, contractRecordExportExcelVO);
            contractRecordExportExcelVO.setSecretStr(e.getSecret() == 2 ? "机密" : "非机密");
            if (e.getStatus() != null) {
                contractRecordExportExcelVO.setStatusStr(ContractStatusEnum.of(e.getStatus()).getName());
            }
            if (e.getPerformance() != null) {
                contractRecordExportExcelVO.setPerformanceStr(e.getPerformance() == 2 ? "已完成" : "进行中");
            }

            contractRecordExportExcelVO.setContractTypeStr(ContractTypeEnum.of(e.getContractType()).getName());
            contractRecordExportExcelVO.setCreaterAndCreateTime(e.getCreater() + "/" + DateUtil.toString(e.getCreateTime()));
            contractRecordExportExcelVO.setPaymentStatusStr(ContractPaymentStatusEnum.of(e.getPaymentStatus()).getName());
            contractRecordExportExcelVO.setDeptStr(e.getAgentDeptOneName() + '_' + e.getAgentDeptTwoName());
            contractRecordExportExcelVO.setContractBeginDayStr(DateUtil.toString(e.getContractBeginDay(), "yyyy-MM-dd"));
            contractRecordExportExcelVO.setContractEndDayStr(DateUtil.toString(e.getContractEndDay(), "yyyy-MM-dd"));
            contractRecordExportExcelVO.setSignDayStr(DateUtil.toString(e.getSignDay(), "yyyy-MM-dd"));
            List<ContractFileRecord> files = fileRecordMap.get(e.getContractId());
            if (files != null && files.size() > 0) {
                StringBuilder stringBuilder = new StringBuilder();
                files.forEach(innerFile -> {
                    Integer index = innerFile.getFileSrc().lastIndexOf("/");
                    if (innerFile.getFileSrc() != null && index != -1) {
                        stringBuilder.append(innerFile.getFileSrc().substring(index + 1)).append(",");
                    } else {
                        stringBuilder.append("");
                    }
                });
                stringBuilder.deleteCharAt(stringBuilder.length() - 1);
                contractRecordExportExcelVO.setContractFileStr(stringBuilder.toString());
            }

            contractRecordExportExcelVOS.add(contractRecordExportExcelVO);
        }

        if (CollectionUtils.isEmpty(contractRecordExportExcelVOS)) {
            contractRecordExportExcelVOS = new ArrayList<>();
            contractRecordExportExcelVOS.add(new ContractRecordExportExcelVO());
        }

        // 封装Excel对象
        LinkedHashMap<String, String> fieldMap = Maps.newLinkedHashMap();

        fieldMap.put("sort", "排序");
        fieldMap.put("contractId", "ID");
        fieldMap.put("name", "合同名称");
        fieldMap.put("contractNo", "合同编号");
        fieldMap.put("subjectAmountYuan", "标的金额");
        fieldMap.put("subject", "合同主体");
        fieldMap.put("contractBeginDayStr", "合同始期");
        fieldMap.put("contractEndDayStr", "合同终期");
        fieldMap.put("contractTypeStr", "合同类型");
        fieldMap.put("signDayStr", "签订日期");
        fieldMap.put("agentStr", "经办人");
        fieldMap.put("agentCompanyName", "所属公司");
        fieldMap.put("deptStr", "所属管理部门");
        fieldMap.put("secretStr", "是否机密");
        fieldMap.put("performanceStr", "合同履行情况");
        fieldMap.put("paymentStatusStr", "付款状态");
        fieldMap.put("statusStr", "合同状态");
        fieldMap.put("createrAndCreateTime", "创建人/创建时间");
        fieldMap.put("contractFileStr", "合同附件");

        ExportExcel<ContractRecordExportExcelVO> excel = new ExportExcel<>(contractRecordExportExcelVOS, fieldMap, true);

        return excel;
    }

    @Override
    public void downLoadFile(HttpServletResponse response, String urlFile) {
        String urlPath = urlFile;
        BufferedInputStream bin = null;
        HttpURLConnection httpURLConnection = null;
        OutputStream out = null;
        String[] params = urlPath.split("/");
        String fileName = "default.file";
        if (params != null && params.length > 0) {
            fileName = params[params.length - 1];
        }
        // 设置强制下载不打开
        response.setContentType("application/force-download");
        try {
            // 设置文件名
            response.addHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileName, "UTF-8"));
        } catch (UnsupportedEncodingException e) {
            logger.error("不支持的编码格式", e);
        }
        try {
            // 统一资源
            URL url = new URL(urlPath);
            // 连接类的父类，抽象类
            URLConnection urlConnection = url.openConnection();
            // http的连接类
            httpURLConnection = (HttpURLConnection)urlConnection;
            // 设置超时
            httpURLConnection.setConnectTimeout(1000 * 5);
            // 设置请求方式，默认是GET
            httpURLConnection.setRequestMethod("GET");
            // 设置字符编码
            httpURLConnection.setRequestProperty("Charset", "UTF-8");
            // 打开到此 URL引用的资源的通信链接（如果尚未建立这样的连接）。
            httpURLConnection.connect();

            // 建立链接从请求中获取数据
            bin = new BufferedInputStream(httpURLConnection.getInputStream());

            out = response.getOutputStream();
            int size = 0;
            long len = 0;
            byte[] buf = new byte[2048];
            while ((size = bin.read(buf)) != -1) {
                len += size;
                out.write(buf, 0, size);
            }
            // 关闭资源
            bin.close();
            out.close();
            logger.info("文件下载成功,文件大小：" + len / 1024 + "kb");
        } catch (MalformedURLException e) {

        } catch (IOException e) {
            logger.error("文件下载失败！", e);
        } finally {
            if (bin != null) {
                try {
                    bin.close();
                } catch (IOException e) {
                    logger.error("BufferedInputStream流关闭失败！", e);
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {

                    logger.error("OutputStream流关闭失败！", e);
                }
            }
            if (httpURLConnection != null) {
                httpURLConnection.disconnect();
            }
        }
    }

    private String getContractNo(Integer companyId, Integer deptId) {
        String companyAbbreviation = ContractCompanyEnum.of(companyId).getAbbreviation();
        String deptAbbreviation = ContractDeptEnum.of(deptId).getAbbreviation();
        String prefix = companyAbbreviation + "-" + deptAbbreviation + "-" + "HT-";
        ContractRecordQuery query = new ContractRecordQuery();
        query.setContractNo(prefix);
        String appendFix = "001";
        List<ContractRecord> contractRecords = contractRecordService.listByQuery(query);
        if (contractRecords != null && contractRecords.size() > 0) {
            List<String> list = contractRecords.stream().sorted(Comparator.comparing(ContractRecord::getContractNo).reversed()).map(e -> e.getContractNo()).collect(Collectors.toList());
            String numStr = list.get(0);
            String[] array = numStr.split("-");
            numStr = array[array.length - 1];
            Integer num = Integer.parseInt(numStr) + 1;
            appendFix = String.format("%03d", num);
            prefix += appendFix;
        } else {
            prefix += appendFix;
        }

        return prefix;
    }

    private String narrow(Object dividend) {
        if (Objects.isNull(dividend)) {
            return "";
        }
        double div = MathUtil.div(dividend.toString(), String.valueOf(MasterDict.COEFFICIENT_MAGNIFICATION), 2);
        BigDecimal b = new BigDecimal(div);
        return b.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
    }
}
